package com.hkyp.ss.course.provider.impl;

import com.github.wenhao.jpa.Specifications;
import com.hkyp.ss.course.apis.CourseService;
import com.hkyp.ss.course.apis.dto.common.PageReq;
import com.hkyp.ss.course.apis.dto.common.PageResp;
import com.hkyp.ss.course.apis.dto.query.CourseSpecification;
import com.hkyp.ss.course.apis.dto.request.HomePageCourseDTO;
import com.hkyp.ss.course.apis.dto.response.CourCommVoterVO;
import com.hkyp.ss.course.apis.dto.response.CourseSummaryVO;
import com.hkyp.ss.course.apis.dto.response.CourseVO;
import com.hkyp.ss.course.apis.enumu.CourseStatusEnum;
import com.hkyp.ss.course.apis.enumu.DeletedEnum;
import com.hkyp.ss.course.apis.enumu.YesNoEnum;
import com.hkyp.ss.course.apis.exception.DaoException;
import com.hkyp.ss.course.apis.exception.UnacceptableException;
import com.hkyp.ss.course.apis.utils.BeanMapper;
import com.hkyp.ss.course.provider.model.Course;
import com.hkyp.ss.course.provider.model.CourseComment;
import com.hkyp.ss.course.provider.model.mediate.CourCommVoter;
import com.hkyp.ss.course.provider.model.mediate.UserCourseCollection;
import com.hkyp.ss.course.provider.model.mediate.UserCourseLike;
import com.hkyp.ss.course.provider.model.mediate.UserCourseStudy;
import com.hkyp.ss.course.provider.repository.CourCommRepository;
import com.hkyp.ss.course.provider.repository.CourseRepository;
import com.hkyp.ss.course.provider.repository.mediate.UserCourCollRepository;
import com.hkyp.ss.course.provider.repository.mediate.UserCourLikeRepository;
import com.hkyp.ss.course.provider.repository.mediate.UserCourStudyRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service(version = "1.0")
@Transactional(rollbackFor = Exception.class)
public class CourseServiceImpl implements CourseService {
    @Autowired
    private UserCourStudyRepository courStudyRepository;
    @Autowired
    private  CourseRepository courseRepository;
    @Autowired
    private UserCourLikeRepository userCourLikeRepository;

    @Autowired
    private UserCourCollRepository userCourCollRepository;

    @Autowired
    private CourCommRepository courCommRepository;
    @Autowired
    private UserCourStudyRepository userCourStudyRepository;

    public void saveCourse(List courses){

        System.out.println(courseRepository.saveAll(courses));


    }

    @Transactional(readOnly = true)
    public List<CourseSummaryVO> selectRecommendedCourse(Long userId){
        List<Course> courses = courseRepository.findAllByStatusAndRecommendAndDeleted(CourseStatusEnum.NORMAL.getCourseStatus(), YesNoEnum.YES.getCode(),DeletedEnum.NO.getCode());
        List<CourseSummaryVO> summaryVOList = new ArrayList<>();
        if(CollectionUtils.isEmpty(courses)){
            return summaryVOList;
        }

        Set<Long> cidSet = courses.stream().map(Course::getId).collect(Collectors.toSet());
        summaryVOList = BeanMapper.mapList(courses, CourseSummaryVO.class);


        //todo
        // 如果用户id是null,代表没有登录，这时点赞或收藏状态全是否的状态
        if(userId == null){
            return summaryVOList;
        }

        Map<Long, CourseSummaryVO> courseSummaryVOMap = summaryVOList.stream().collect(Collectors.toMap(CourseSummaryVO::getId, courseSummaryVO -> courseSummaryVO));

        List<UserCourseLike> userCourseLikeList = userCourLikeRepository.findAllByUserIdAndCourseIdIn(userId,cidSet);
        //如果不为空，设置liked值
        if(!CollectionUtils.isEmpty(userCourseLikeList)){
            userCourseLikeList.forEach(userCourseLike -> {
                CourseSummaryVO courseSummaryVO = courseSummaryVOMap.get(userCourseLike.getCourseId());
                courseSummaryVO.setLiked(1);
            });
        }
        log.info(""+userCourseLikeList);

        /***
         *  是否学习过、评论过、收藏过赋值
         */
        Map<Long, UserCourseStudy> userCourseStudyMap = new HashMap<>();
        Map<Long, CourseComment> courseCommentMap = new HashMap<>();
        Map<Long, UserCourseCollection> userCourseCollectionMap = new HashMap<>();
        //是否学习过
        List<UserCourseStudy> userCourseStudyList = courStudyRepository.findAllByUserIdAndCourseIdInAndStatusEquals(userId, cidSet, YesNoEnum.NO.getCode());
        if(!CollectionUtils.isEmpty(userCourseStudyList)){
            userCourseStudyMap = userCourseStudyList
                    .stream()
                    .collect(Collectors.toMap(UserCourseStudy::getCourseId, obj -> obj));
        }

        //是否发表过课评
        List<CourseComment> courseCommentList = courCommRepository.findAllByCourseIdInAndUserIdEqualsAndDeletedEquals(cidSet, userId, YesNoEnum.NO.getCode());
        if(!CollectionUtils.isEmpty(courseCommentList)){
            courseCommentMap = courseCommentList
                    .stream()
                    .collect(Collectors.toMap(CourseComment::getCourseId, obj -> obj));
        }

        //是否收藏过该课评
        List<UserCourseCollection> userCourseCollectionList = userCourCollRepository.findAllByUserIdAndAndCourseIdIn(userId, cidSet);
        if(!CollectionUtils.isEmpty(userCourseCollectionList)){
            userCourseCollectionMap = userCourseCollectionList
                    .stream()
                    .collect(Collectors.toMap(UserCourseCollection::getCourseId, obj -> obj));
        }

        Map<Long, UserCourseStudy> userCourseStudyMapLam = userCourseStudyMap;
        Map<Long, CourseComment> courseCommentMapLam = courseCommentMap;
        Map<Long, UserCourseCollection> userCourseCollectionMapLam = userCourseCollectionMap;
        summaryVOList.forEach(responseDTO -> {
            if(userCourseStudyMapLam.get(responseDTO.getId())!=null){
                responseDTO.setStudied(YesNoEnum.YES.getCode());
            }
            if(courseCommentMapLam.get(responseDTO.getId())!=null){
                responseDTO.setCommented(YesNoEnum.YES.getCode());
                ;
            }
            if(userCourseCollectionMapLam.get(responseDTO.getId())!=null){
                responseDTO.setCollected(YesNoEnum.YES.getCode());
            }
        });

        log.info(""+summaryVOList);

        return summaryVOList;

    }
    @Transactional(readOnly = true)
    @Override
    public CourseVO selectCourseNaked(Long id) {

        Course course = courseRepository.findById(id).orElseGet(null);
        if(course == null){
            return null;
        }

        return BeanMapper.map(course,CourseVO.class);
    }

    public void studyCourse(Long userId, Long courseId) throws UnacceptableException{

        UserCourseStudy po = userCourStudyRepository.findByUserIdAndCourseIdAndStatusEquals(userId, courseId, CourseStatusEnum.NORMAL.getCourseStatus());
        if(po != null){
            throw new UnacceptableException("您已学习过此课程");
        }
        Course course = courseRepository.findById(courseId).orElseThrow(() -> new UnacceptableException("操作的对象不存在"));
        if(!Objects.equals(course.getStatus(),CourseStatusEnum.NORMAL.getCourseStatus())){
            throw new UnacceptableException("该课程已删除或下架");
        }
        UserCourseStudy userCourseStudy = new UserCourseStudy();
        userCourseStudy.setCourseId(courseId);
        userCourseStudy.setUserId(userId);
        userCourseStudy.setStatus(CourseStatusEnum.NORMAL.getCourseStatus());
        userCourseStudy.setCreateAt(System.currentTimeMillis());
        userCourStudyRepository.save(userCourseStudy);
    }

    @Override
    @Transactional(readOnly = true)
    public PageResp<CourseSummaryVO> selectHomePageCourse(HomePageCourseDTO homePageCourseDTO, PageReq pageReq) {

        Page<Course> page = courseRepository.findAll(new CourseSpecification(homePageCourseDTO),pageReq.toPageable());
        List<Course> courses = page.getContent();
        List<CourseSummaryVO> summaryVOList = BeanMapper.mapList(courses, CourseSummaryVO.class);

        log.info(""+summaryVOList);

        return new PageResp(page,summaryVOList);
    }


    @Transactional(readOnly = true)
    public PageResp<CourseSummaryVO> selectHomePageCourseV2(HomePageCourseDTO homePageCourseDTO, PageReq pageReq,Long userId) {

        log.info("service端入参："+homePageCourseDTO+","+pageReq);
        CourseSpecification specification = new CourseSpecification(homePageCourseDTO);

        log.info("条件参数："+specification+","+pageReq.toPageable());
        Page<Course> page = courseRepository.findAll(specification, pageReq.toPageable());
        List<Course> courses = page.getContent();
        List<CourseSummaryVO> summaryVOList = BeanMapper.mapList(courses, CourseSummaryVO.class);
        if(userId == null){
            return new PageResp<>(page,summaryVOList);
        }

        Set<Long> cidSet = courses.stream().map(Course::getId).collect(Collectors.toSet());
        log.info("单页课程id集合：{}",cidSet);

        /***
         *  是否学习过、评论过、收藏过赋值
         */
        Map<Long, UserCourseStudy> userCourseStudyMap = new HashMap<>();
        Map<Long, CourseComment> courseCommentMap = new HashMap<>();
        Map<Long, UserCourseCollection> userCourseCollectionMap = new HashMap<>();
        //是否学习过
        List<UserCourseStudy> userCourseStudyList = courStudyRepository.findAllByUserIdAndCourseIdInAndStatusEquals(userId, cidSet, YesNoEnum.NO.getCode());
        if(!CollectionUtils.isEmpty(userCourseStudyList)){
              userCourseStudyMap = userCourseStudyList
                            .stream()
                            .collect(Collectors.toMap(UserCourseStudy::getCourseId, obj -> obj));
        }

        //是否发表过课评
        List<CourseComment> courseCommentList = courCommRepository.findAllByCourseIdInAndUserIdEqualsAndDeletedEquals(cidSet, userId, YesNoEnum.NO.getCode());
        if(!CollectionUtils.isEmpty(courseCommentList)){
            courseCommentMap = courseCommentList
                    .stream()
                    .collect(Collectors.toMap(CourseComment::getCourseId, obj -> obj));
        }

        //是否收藏过该课评
        List<UserCourseCollection> userCourseCollectionList = userCourCollRepository.findAllByUserIdAndAndCourseIdIn(userId, cidSet);
        if(!CollectionUtils.isEmpty(userCourseCollectionList)){
             userCourseCollectionMap = userCourseCollectionList
                    .stream()
                    .collect(Collectors.toMap(UserCourseCollection::getCourseId, obj -> obj));
        }

        Map<Long, UserCourseStudy> userCourseStudyMapLam = userCourseStudyMap;
        Map<Long, CourseComment> courseCommentMapLam = courseCommentMap;
        Map<Long, UserCourseCollection> userCourseCollectionMapLam = userCourseCollectionMap;
        summaryVOList.forEach(responseDTO -> {
            if(userCourseStudyMapLam.get(responseDTO.getId())!=null){
                responseDTO.setStudied(YesNoEnum.YES.getCode());
            }
            if(courseCommentMapLam.get(responseDTO.getId())!=null){
                responseDTO.setCommented(YesNoEnum.YES.getCode());
            }
            if(userCourseCollectionMapLam.get(responseDTO.getId())!=null){
                responseDTO.setCollected(YesNoEnum.YES.getCode());
            }
        });

        log.info(""+summaryVOList);

        return new PageResp<>(page,summaryVOList);
    }


    @Override
    @Transactional(readOnly = true)
    public PageResp<CourseSummaryVO> selectCourseByKeyword(String keyword, PageReq pageReq) {

        Page<Course> page = courseRepository.findCoursesByKeyword(keyword,pageReq.toPageable());
        List<Course> courses = page.getContent();
        List<CourseSummaryVO> summaryVOList = BeanMapper.mapList(courses, CourseSummaryVO.class);

        log.info(""+summaryVOList);
        return new PageResp<>(page,summaryVOList);

    }

    // 增加已收藏、已撰写字段
    @Override
    @Transactional(readOnly = true)
    public CourseVO selectCourse(Long cid,Long userId) {

        Course course = courseRepository.findById(cid).orElseGet(Course::new);
        CourseVO courseVO = BeanMapper.map(course, CourseVO.class);
        if(userId == null){
            courseVO.setCollected(YesNoEnum.NO.getCode());
            courseVO.setEdited(YesNoEnum.NO.getCode());
            log.info(""+courseVO);
            return courseVO;
        }
        UserCourseCollection userCourseCollection = userCourCollRepository.findByCourseIdAndUserId(cid, userId);
        if(userCourseCollection == null){
            courseVO.setCollected(YesNoEnum.NO.getCode());
        }else {
            courseVO.setCollected(YesNoEnum.YES.getCode());
        }
        List<CourseComment> courseComments = courCommRepository.findByCourseIdAndUserIdAndDeletedAndStatus(cid, userId, DeletedEnum.NO.getCode(),CourseStatusEnum.NORMAL.getCourseStatus());
        if(CollectionUtils.isEmpty(courseComments)){
            courseVO.setEdited(YesNoEnum.NO.getCode());
        }else {
            // 如果用户有写过课评，返回课评id
            courseVO.setEdited(YesNoEnum.YES.getCode());
            courseVO.setCcId(courseComments.get(0).getId());
        }

        log.info(""+courseVO);
        return courseVO;
    }

    @Override
    public CourCommVoterVO likeCourse(Long cid, Integer action, Long userId) {
        CourCommVoterVO courCommVoterVO = new CourCommVoterVO();
        if(action == null){
            return null;
        }

        UserCourseLike userCourseLike = userCourLikeRepository.findByUserIdAndCourseId(userId,cid);
        Course course = courseRepository.findById(cid).orElseThrow(()->new DaoException("不存在此课程"));
        //action=1表示要点赞
        if(action == 1){
            // 对于已经点过赞还要点赞的情况
            if(userCourseLike !=null){
                courCommVoterVO.setAction(action);
                courCommVoterVO.setLike(course.getUserLike());
                return courCommVoterVO;
            }
            UserCourseLike userCourseLike1 = new UserCourseLike();
            userCourseLike1.setCourseId(cid);
            userCourseLike1.setUserId(userId);
            userCourseLike1.setCreateAt(System.currentTimeMillis());
            userCourLikeRepository.save(userCourseLike1);
            course.setUserLike(course.getUserLike()+1);
        }else if(action == 0){
            // 对于没有点过赞却要取消点赞的情况
            if(userCourseLike ==null){
                courCommVoterVO.setAction(action);
                courCommVoterVO.setLike(course.getUserLike());
                return courCommVoterVO;
            }

            userCourLikeRepository.deleteById(userCourseLike.getId());
            course.setUserLike(course.getUserLike()-1);
        }
        courseRepository.save(course);
        courCommVoterVO.setAction(action);
        courCommVoterVO.setLike(course.getUserLike());

        return courCommVoterVO;
    }

    @Override
    public Map collectCourse(Long cid, Integer action, Long userId) {
        if(action == null){
            return null;
        }

        UserCourseCollection userCourseCollection = userCourCollRepository.findByCourseIdAndUserId(cid,userId);
        Course course = courseRepository.findById(cid).orElseThrow(()->new DaoException("不存在此课程"));
        Map map = new HashMap<>();
        //action=1表示要收藏
        if(action == 1){
            if(userCourseCollection !=null){
               log.warn("您已收藏过此课程");
                map.put("action",action);
                map.put("collectionNum",course.getCollection());
                return map;
            }
            UserCourseCollection userCourseCollection1 = new UserCourseCollection();
            userCourseCollection1.setCourseId(cid);
            userCourseCollection1.setUserId(userId);
            userCourseCollection1.setCreateAt(System.currentTimeMillis());
            userCourCollRepository.save(userCourseCollection1);
            course.setCollection(course.getCollection()+1);
        }else if(action == 0){
            if(userCourseCollection ==null){
                log.warn("用户在对未收藏的课程执行取消收藏");
                map.put("action",action);
                map.put("collectionNum",course.getCollection());
                return map;
            }
            userCourCollRepository.deleteById(userCourseCollection.getId());
            course.setCollection(course.getCollection()-1);
        }

        courseRepository.save(course);
        map.put("action",action);
        map.put("collectionNum",course.getCollection());


        return map;
    }


}
